DatabaseQueue 和 DatabasePool
DatabaseQueue 和 DatabasePool 是 SQLite API 中负责数据库并发模型和生命周期管理的组件。
它们决定了:
- 数据库如何被调度访问
- 是否支持并发读取
- Database 实例的生命周期边界
- 事务与读写隔离行为
两者都不直接执行 SQL,而是通过向回调中提供 Database 实例来完成实际操作。
DatabaseQueue
DatabaseQueue 提供 串行(Serial)数据库访问模型。
所有数据库操作(读和写)都会在同一队列中顺序执行。
类型定义
并发模型
- 所有
read和write调用 串行执行 - 任意时刻只有一个
Database实例在工作 - 不存在并发访问、锁竞争或读写冲突问题
基本用法
read 与 write
read:语义上表示只读操作write:语义上表示写操作
在 DatabaseQueue 中:
- 两者在行为上 没有并发差异
- 主要用于提高代码可读性和表达意图
inDatabase
inDatabase 允许直接在队列中执行一段数据库逻辑。
通常用于:
- 管理类操作
- 不区分读写的内部逻辑
inTranscation
在队列级别开启事务。
说明:
- 该方法作用于队列关联的 Database
- 适合整体事务控制
- 不支持并发嵌套
使用场景
推荐使用 DatabaseQueue 的情况:
- 写操作频繁
- 业务逻辑依赖严格执行顺序
- 脚本简单,数据量中小
- 希望避免并发带来的复杂性
DatabasePool
DatabasePool 提供 并发读取 + 串行写入 的访问模型。
它允许多个只读操作并发执行,同时保证写操作的安全性。
类型定义
并发模型
- 多个
read回调可并发执行 write回调 串行执行- 写操作会与所有读操作进行必要的同步
这种模型非常适合 读多写少 的场景。
基本用法
read 与 write 的语义差异
在 DatabasePool 中:
-
read- 使用只读连接
- 可并发执行
- 不允许写操作
-
write- 使用写连接
- 串行执行
- 会阻塞其他写操作
使用场景
推荐使用 DatabasePool 的情况:
- 查询频繁、写入较少
- 大量列表、搜索、统计类查询
- 多个脚本或任务同时读取同一数据库
- 对吞吐量和响应性能有要求
DatabaseQueue vs DatabasePool
核心区别对比
如何选择
优先选择 DatabaseQueue,如果:
- 你不确定是否需要并发
- 写操作较多
- 更看重逻辑简单和稳定性
选择 DatabasePool,如果:
- 数据库以查询为主
- 有明显的并发读取需求
- 希望提高整体性能
生命周期管理
两者都提供相同的生命周期管理方法:
releaseMemory
释放 SQLite 内部缓存。
interrupt
中断当前正在执行的数据库操作。
close
关闭数据库连接,释放资源。
说明:
- 调用
close后,不应再执行任何数据库操作 - 关闭后相关的
Database和Statement都将失效
使用注意事项
- 不要在
read回调中执行写操作(尤其是 DatabasePool) - 不要在回调外部保存
Database实例 - 不要在多个 Queue / Pool 之间混用同一个 Database
- 确保所有事务在同一个回调内完成
总结
DatabaseQueue 和 DatabasePool 是 SQLite API 中最关键的并发抽象层:
DatabaseQueue:简单、安全、顺序明确DatabasePool:高性能、适合读密集型场景
